home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs2.zip / UTIL / uupoll.c < prev   
C/C++ Source or Header  |  1993-09-26  |  38KB  |  1,026 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    Program:    uupoll.c              22 September 1989             */
  3. /*    Author:     Andrew H. Derbyshire                                */
  4. /*                Kendra Electronic Wonderworks                       */
  5. /*                P.O. Box 132                                        */
  6. /*                Arlington, MA 02174                                 */
  7. /*    Internet:   help@kew.com                                        */
  8. /*    Function:   Performs autopoll functions for UUCICO              */
  9. /*    Language:   Borland C++ 3.1                                     */
  10. /*--------------------------------------------------------------------*/
  11.  
  12. /*--------------------------------------------------------------------*/
  13. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  14. /*       Wonderworks.                                                 */
  15. /*                                                                    */
  16. /*       All rights reserved except those explicitly granted by       */
  17. /*       the UUPC/extended license agreement.                         */
  18. /*--------------------------------------------------------------------*/
  19.  
  20. /*--------------------------------------------------------------------*/
  21. /*    Usage:      uupoll [-r 0] [-f hhmm] [-i hhmm|0400 ]             */
  22. /*                       [-d hhmm] [-e hhmm]                          */
  23. /*                       [-a hhmm] [-x debug] [-s systems]            */
  24. /*                       [-c hhmm] [-C command] [-B command]          */
  25. /*                                                                    */
  26. /*                Where:                                              */
  27. /*                                                                    */
  28. /*                -r 0     specifies that UUCICO is to run            */
  29. /*                         into passive mode when waiting to          */
  30. /*                         poll out                                   */
  31. /*                                                                    */
  32. /*                -r 1     specifies that UUCICO will not run         */
  33. /*                         in passive mode while waiting to           */
  34. /*                         poll out, but polling out will             */
  35. /*                         occur.                                     */
  36. /*                                                                    */
  37. /*                -f hhmm  is the first time in the day that          */
  38. /*                         UUCICO is to poll out.  If omitted,        */
  39. /*                         polling begins after the interval          */
  40. /*                         specified with -i.                         */
  41. /*                                                                    */
  42. /*                -i hhmm  the interval the UUCICO is to poll         */
  43. /*                         out at.  If omitted, a period of 4         */
  44. /*                         hours will be used.                        */
  45. /*                                                                    */
  46. /*                -d hhmm  Terminate polling after hhmm.              */
  47. /*                         Default is not to terminate.               */
  48. /*                                                                    */
  49. /*                -e hhmm  Terminate polling at hhmm                  */
  50. /*                         Default is not to terminate.               */
  51. /*                                                                    */
  52. /*                -a hhmm  Automatically poll actively using the      */
  53. /*                         system name "any" after any                */
  54. /*                         successful inbound poll if hhmm have       */
  55. /*                         past since last poll.  hhmm may be         */
  56. /*                         0000.                                      */
  57. /*                                                                    */
  58. /*                -c hhmm  Run a command at hhmm to clean the UUPC    */
  59. /*                         spool at this time every day.  Default is  */
  60. /*                         never.                                     */
  61. /*                                                                    */
  62. /*                -C cmd   Run command 'cmd' at the specified by      */
  63. /*                         -c.  The default is UUCLEAN.               */
  64. /*                                                                    */
  65. /*                -B cmd   Run command cmd before each active call    */
  66. /*                         out to batch up any work.  Default is      */
  67. /*                         run nothing.                              */
  68. /*                                                                    */
  69. /*                In addition, the following flags will be passed     */
  70. /*                to UUCICO:                                          */
  71. /*                                                                    */
  72. /*                -s system      system name to poll.  By default,    */
  73. /*                               UUCICO will be invoked with          */
  74. /*                               '-s all' followed by '-s any'.       */
  75. /*                                                                    */
  76. /*                -x n           debug level.   The default level     */
  77. /*                               is 1.                                */
  78. /*--------------------------------------------------------------------*/
  79.  
  80. /*--------------------------------------------------------------------*/
  81. /*                          RCS Information                           */
  82. /*--------------------------------------------------------------------*/
  83.  
  84. /*
  85.  *    $Id: uupoll.c 1.14 1993/09/27 00:45:20 ahd Exp $
  86.  *
  87.  *    $Log: uupoll.c $
  88.  * Revision 1.14  1993/09/27  00:45:20  ahd
  89.  * Make command syncs to get around bug in execute() under OS/2
  90.  *
  91.  * Revision 1.13  1993/09/20  04:41:54  ahd
  92.  * OS/2 2.x support
  93.  *
  94.  * Revision 1.12  1993/07/31  16:26:01  ahd
  95.  * Changes in support of Robert Denny's Windows support
  96.  *
  97.  * Revision 1.11  1993/07/19  02:52:11  ahd
  98.  * Up memory access room
  99.  *
  100.  * Revision 1.10  1993/06/06  15:04:05  ahd
  101.  * Allow for batch command to run before regularly scheduled poll out
  102.  *
  103.  * Revision 1.9  1993/05/13  01:39:04  ahd
  104.  * Additional fix for correctly handling UUCLEAN once and only once daily
  105.  *
  106.  * Revision 1.8  1993/05/11  03:25:17  ahd
  107.  * Don't loop when sleeping for autoclean -- get it over with
  108.  *
  109.  * Revision 1.7  1993/04/14  10:29:53  ahd
  110.  * Correct invalid exit time if both -e and -f flags specified
  111.  *
  112.  * Revision 1.6  1993/04/10  21:25:16  dmwatt
  113.  * Add Windows/NT support
  114.  *
  115.  * Revision 1.6  1993/04/10  21:25:16  dmwatt
  116.  * Add Windows/NT support
  117.  *
  118.  * Revision 1.5  1993/04/04  04:57:01  ahd
  119.  * Return exit code of UUCICO upon exit
  120.  *
  121.  * Revision 1.4  1993/03/06  23:04:54  ahd
  122.  * Add cr after auto-clean message
  123.  *
  124.  * Revision 1.3  1992/11/20  12:41:01  ahd
  125.  * Fix TZ change bug
  126.  *
  127.  * Revision 1.2  1992/11/15  04:45:46  ahd
  128.  * Correct polling for days time zone changes
  129.  *
  130.  * Revision 1.1  1992/11/15  04:29:22  ahd
  131.  * Initial revision
  132.  *
  133.  * Revision 1.1  1992/04/27  00:30:13  ahd
  134.  * Initial revision
  135.  *
  136.  */
  137.  
  138. static const char rcsid[] =
  139.          "$Id: uupoll.c 1.14 1993/09/27 00:45:20 ahd Exp $";
  140.  
  141. /*--------------------------------------------------------------------*/
  142. /*                        System include file                         */
  143. /*--------------------------------------------------------------------*/
  144.  
  145. #include <ctype.h>
  146. #include <dos.h>
  147. #include <limits.h>
  148. #include <process.h>
  149. #include <stdio.h>
  150. #include <stdlib.h>
  151. #include <string.h>
  152. #include <time.h>
  153. #include <conio.h>
  154. #include <direct.h>
  155. #include <signal.h>           /* Ctrl-Break handler               */
  156.  
  157. #if  defined(WIN32) || defined(FAMILYAPI) || defined(_Windows) || defined(__OS2__)
  158. #define NOCBREAK
  159. #elif defined(__TURBOC__)
  160. #include <alloc.h>
  161. unsigned _stklen = 3172;            /* Reduce memory usage           */
  162. unsigned _heaplen = 2048;           /* Reduce memory usage           */
  163. #else
  164. static int setcbrk(char state);
  165. #endif
  166.  
  167. /*--------------------------------------------------------------------*/
  168. /*                    UUPC/extended include files                     */
  169. /*--------------------------------------------------------------------*/
  170.  
  171. #include "getopt.h"
  172. #include "lib.h"
  173. #include "timestmp.h"
  174. #include "ssleep.h"
  175. #include "arpadate.h"
  176. #include "safeio.h"
  177. #include "dater.h"
  178. #include "execute.h"
  179.  
  180. /*--------------------------------------------------------------------*/
  181. /*                        Typedefs and macros                         */
  182. /*--------------------------------------------------------------------*/
  183.  
  184. typedef int hhmm;
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*                  Prototypes and global variables                   */
  188. /*--------------------------------------------------------------------*/
  189.  
  190.  void
  191. #ifdef __TURBOC__
  192. __cdecl
  193. #endif
  194.  Catcher( int sig );
  195.  
  196. static active(char *Rmtname, int debuglevel, const char *logname);
  197.  
  198. static void    busywork( time_t next);
  199.  
  200. static int runCommand( char *command, const boolean sync);
  201.  
  202. static time_t  nextpoll( hhmm first, hhmm interval );
  203.  
  204. static boolean     notanumber( char *number);
  205.  
  206. static void    usage( char *name );
  207.  
  208.  static int passive( time_t next,
  209.                      int debuglevel,
  210.                      const char *logname,
  211.                      const char *modem );
  212.  
  213. static hhmm    firstpoll(hhmm interval);
  214.  
  215. static void    uuxqt( const int debuglevel, boolean sync);
  216.  
  217. static time_t LifeSpan( time_t duration, time_t stoptime );
  218.  
  219. static time_t now;            /* Current time, updated at start of
  220.                                  program and by busywork() and
  221.                                  runCommand()                        */
  222.  
  223. currentfile();
  224.  
  225. /*--------------------------------------------------------------------*/
  226. /*    m a i n                                                         */
  227. /*                                                                    */
  228. /*    main program                                                    */
  229. /*--------------------------------------------------------------------*/
  230.  
  231.  void main( int argc , char *argv[] )
  232.  {
  233.  
  234.    int option;
  235.    hhmm first = - 1;
  236.    hhmm interval = -1;
  237.    hhmm stoptime = -1;
  238.    hhmm duration = -1;
  239.    hhmm autowait = -1;
  240.    hhmm cleanup  = -1;
  241.    time_t cleannext = LONG_MAX;
  242.  
  243.    time_t exittime;
  244.    int nopassive = 2;
  245.    boolean done = FALSE;
  246.    char *Rmtname = NULL;
  247.    char *CleanCommand = "uuclean";
  248.    char *logname = NULL;
  249.    char *modem   = NULL;
  250.    char *batchCommand   = NULL;
  251.    int returnCode = 0;
  252.  
  253. #ifndef NOCBREAK
  254.    boolean cbrk;
  255. #endif
  256.  
  257.    banner(argv);
  258.  
  259.    if (!configure( B_UUPOLL ))
  260.       panic();
  261.  
  262.    tzset();
  263.    time( &now );
  264.  
  265.     if( signal( SIGINT, Catcher ) == SIG_ERR )
  266.     {
  267.         fprintf( stderr, "uupoll: Couldn't set SIGINT\n" );
  268.         panic();
  269.     }
  270.  
  271.    while((option = getopt(argc, argv, "m:a:B:c:C:d:e:f:l:i:s:r:x:")) != EOF)
  272.    switch(option)
  273.    {
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*       Automatically poll "any" after an incoming phone call        */
  277. /*--------------------------------------------------------------------*/
  278.  
  279.       case 'a':
  280.          if (notanumber(optarg))
  281.             usage( argv[0] );
  282.          autowait = (hhmm) hhmm2sec( atoi(optarg) );
  283.          break;
  284.  
  285. /*--------------------------------------------------------------------*/
  286. /*                    Batching command to execute                     */
  287. /*--------------------------------------------------------------------*/
  288.  
  289.       case 'B':
  290.          batchCommand = optarg;
  291.          break;
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*                         First time to poll                         */
  295. /*--------------------------------------------------------------------*/
  296.  
  297.       case 'f':
  298.          if (notanumber(optarg))
  299.             usage( argv[0] );
  300.          first = atoi(optarg);
  301.          if ( interval == -1 )
  302.             interval = 400;
  303.          break;
  304.  
  305. /*--------------------------------------------------------------------*/
  306. /*                         First time to clean                        */
  307. /*--------------------------------------------------------------------*/
  308.  
  309.       case 'c':
  310.          if (notanumber(optarg))
  311.             usage( argv[0] );
  312.          cleanup = atoi(optarg);
  313.          break;
  314.  
  315. /*--------------------------------------------------------------------*/
  316. /*                    Clean-up command to execute                     */
  317. /*--------------------------------------------------------------------*/
  318.  
  319.       case 'C':
  320.          CleanCommand = optarg;
  321.          break;
  322.  
  323. /*--------------------------------------------------------------------*/
  324. /*                          UUCICO log file                           */
  325. /*--------------------------------------------------------------------*/
  326.  
  327.       case 'l':
  328.          logname = optarg;
  329.          break;
  330.  
  331.  
  332. /*--------------------------------------------------------------------*/
  333. /*                            Input modem                             */
  334. /*--------------------------------------------------------------------*/
  335.  
  336.       case 'm':
  337.          modem = optarg;
  338.          break;
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*                          Interval to poll                          */
  342. /*--------------------------------------------------------------------*/
  343.  
  344.       case 'i':
  345.          if (notanumber(optarg))
  346.             usage( argv[0] );
  347.          interval = atoi(optarg);
  348.          nopassive = min(1,nopassive);
  349.          break;
  350.  
  351. /*--------------------------------------------------------------------*/
  352. /*                      Duration to poll                              */
  353. /*--------------------------------------------------------------------*/
  354.  
  355.       case 'e':
  356.          if (notanumber(optarg))
  357.             usage( argv[0] );
  358.          stoptime = atoi(optarg);
  359.          break;
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*                      Time to exit                                  */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.       case 'd':
  366.          if (notanumber(optarg))
  367.             usage( argv[0] );
  368.          duration = atoi(optarg);
  369.          break;
  370.  
  371.  
  372. /*--------------------------------------------------------------------*/
  373. /*                        System name to poll                         */
  374. /*--------------------------------------------------------------------*/
  375.  
  376.       case 's':
  377.          Rmtname = strdup(optarg);
  378.          break;
  379.  
  380. /*--------------------------------------------------------------------*/
  381. /*                            Debug level                             */
  382. /*--------------------------------------------------------------------*/
  383.  
  384.       case 'x':
  385.          if (notanumber(optarg))
  386.             usage( argv[0] );
  387.          debuglevel = atoi(optarg);
  388.          break;
  389.  
  390. /*--------------------------------------------------------------------*/
  391. /*                       Passive polling option                       */
  392. /*--------------------------------------------------------------------*/
  393.  
  394.       case 'r':
  395.          if (notanumber(optarg))
  396.             usage( argv[0] );
  397.          nopassive = atoi(optarg);
  398.          break;
  399.  
  400. /*--------------------------------------------------------------------*/
  401. /*                                Help                                */
  402. /*--------------------------------------------------------------------*/
  403.  
  404.       default:
  405.       case '?':
  406.          usage( argv[0] );
  407.    } /* switch */
  408.  
  409. /*--------------------------------------------------------------------*/
  410. /*             Terminate with error if too many arguments             */
  411. /*--------------------------------------------------------------------*/
  412.  
  413.    if (optind != argc)
  414.    {
  415.       puts("Extra parameters on command line.");
  416.       usage( argv[0] );
  417.    }
  418.  
  419. /*--------------------------------------------------------------------*/
  420. /*       Terminate if neither active polling nor passive polling      */
  421. /*       requested                                                    */
  422. /*--------------------------------------------------------------------*/
  423.  
  424.    if ( nopassive == 2 && (first < 0))
  425.    {
  426.       puts("Must specify -r 0, -f hhmm, or -i hhmm");
  427.       usage( argv[0] );
  428.    }
  429.  
  430. /*--------------------------------------------------------------------*/
  431. /*                        Compute time to exit                        */
  432. /*--------------------------------------------------------------------*/
  433.  
  434.    exittime = LifeSpan( duration, stoptime );
  435.  
  436. /*--------------------------------------------------------------------*/
  437. /*                   Comput first time to poll out                    */
  438. /*--------------------------------------------------------------------*/
  439.  
  440.    if ( (interval > 0) && (first < 0))
  441.       first = firstpoll(interval);
  442.  
  443. /*--------------------------------------------------------------------*/
  444. /*            If running under MS-DOS, enable Cntrl-Break.            */
  445. /*--------------------------------------------------------------------*/
  446.  
  447. #ifndef NOCBREAK
  448. #if defined(__TURBOC__)
  449.  
  450.    cbrk = getcbrk();                /* Get original Cntrl-Break setting */
  451.  
  452.    if (!cbrk)
  453.       setcbrk(1);                   /* Turn it on to allow abort        */
  454.  
  455. #else /*dmw*/
  456.  
  457.    cbrk = setcbrk(1);      /* Turn it on to allow abort; get previous state */
  458.  
  459. #endif
  460. #endif
  461.  
  462. /*--------------------------------------------------------------------*/
  463. /*          Determine first time to perform clean-up, if any          */
  464. /*--------------------------------------------------------------------*/
  465.  
  466.       if (cleanup >= 0)
  467.       {
  468.          cleannext = nextpoll(cleanup, 2400);
  469.          printf("Automatic cleanup via \"%s\" scheduled for %s",
  470.                   CleanCommand, ctime(&cleannext));
  471.       }
  472.  
  473. /*--------------------------------------------------------------------*/
  474. /*                       Beginning of main loop                       */
  475. /*--------------------------------------------------------------------*/
  476.  
  477.    while ( !done && (exittime > now))
  478.    {
  479.       time_t next = LONG_MAX;
  480.       time_t autonext  = now + autowait;
  481.       time_t wait = 10;      /* Time to wait after first panic()    */
  482.       returnCode = 0;
  483.  
  484. /*--------------------------------------------------------------------*/
  485. /*        Determine length of passive poll or wasting of time         */
  486. /*--------------------------------------------------------------------*/
  487.  
  488.       if (first >= 0)
  489.       {
  490.          next = nextpoll(first,interval);
  491.          if ( next > exittime )
  492.             next = exittime;
  493.       }
  494.       else
  495.          next = exittime;
  496.  
  497. /*--------------------------------------------------------------------*/
  498. /*              Disable OS/2 undelete support if desired              */
  499. /*--------------------------------------------------------------------*/
  500.  
  501.    if ( !bflag[ F_UNDELETE ] )
  502.       putenv( "DELDIR=");
  503.  
  504. /*--------------------------------------------------------------------*/
  505. /*    Begin passive polling (with optional active calls system        */
  506. /*    "any") until next active poll or exit time is reached.          */
  507. /*--------------------------------------------------------------------*/
  508.  
  509.       while ((now < next) && ! done )
  510.       {
  511.  
  512.          if ( cleannext <= now )
  513.          {
  514.             printf("Performing auto-clean with command: %s\n",
  515.                      CleanCommand );
  516.             if (runCommand( CleanCommand, FALSE ))
  517.                printerr( CleanCommand );
  518.             cleannext = nextpoll(cleanup,  2400);
  519.          }
  520.  
  521.          if (nopassive)
  522.             busywork(next < cleannext ? next : cleannext);
  523.          else {
  524.             time_t spin;
  525.             returnCode = passive(next < cleannext ? next : cleannext ,
  526.                                  debuglevel, logname , modem );
  527.  
  528.             if (returnCode == 69 )  /* Error in UUCICO?              */
  529.             {                       /* Yes --> Allow time to fix it  */
  530.                spin = now + wait;   /* Figure next wait              */
  531.                wait *= 2 ;          /* Double wait for next time     */
  532.                busywork( spin > next ? next : spin );
  533.                                     /* But only wait till next poll  */
  534.             } /* if (returnCode == 69 ) */
  535.             else {
  536.                wait = 10;
  537.  
  538.                if (returnCode == 0)
  539.                {
  540.                   boolean poll  =  (autowait != -1) &&
  541.                                    (now >= autonext) &&
  542.                                    (now < next);
  543.  
  544.                   uuxqt( debuglevel, poll );
  545.  
  546.                   if ( poll )
  547.                   {
  548.                      returnCode = active("any", debuglevel, logname);
  549.                      autonext = now + autowait;
  550.                   } /* if */
  551.  
  552.                }  /* if (returnCode == 0) */
  553.  
  554.             } /* else */
  555.  
  556.             if ( (now > exittime) && (now < next))
  557.                done = TRUE;
  558.             else if ( returnCode == 100 )
  559.                done = TRUE;
  560.  
  561.          } /* else */
  562.  
  563.       } /* while */
  564.  
  565. /*--------------------------------------------------------------------*/
  566. /*                      Actively poll if needed                       */
  567. /*--------------------------------------------------------------------*/
  568.  
  569.       if ( ! done && (first >= 0) )
  570.       {
  571.          if ( batchCommand != NULL )
  572.          {
  573.             returnCode = runCommand( batchCommand, TRUE );
  574.             if ( returnCode != 0 )
  575.             {
  576.                printmsg(0,
  577.                         "%s exited with %d status, UUPOLL exiting",
  578.                         batchCommand,
  579.                         returnCode);
  580.                break;
  581.             }
  582.          }
  583.  
  584.          returnCode = active(Rmtname,debuglevel,logname);
  585.  
  586.          if ( returnCode == 100 )
  587.             done = TRUE;
  588.  
  589.       } /* if ( ! done && (first >= 0) ) */
  590.  
  591.    } /* while */
  592.  
  593. /*--------------------------------------------------------------------*/
  594. /*                          End of main loop                          */
  595. /*--------------------------------------------------------------------*/
  596.  
  597.    uuxqt( debuglevel, FALSE );   /* One last call to UUXQT                 */
  598.  
  599. #ifndef NOCBREAK
  600.    if (!cbrk)
  601.       setcbrk(0);                /* Restore original Cntrl-Break setting   */
  602. #endif
  603.  
  604.    printmsg(2,"UUPOLL exiting with return code %d", returnCode );
  605.  
  606.    exit(returnCode);
  607.  } /* main */
  608.  
  609. /*--------------------------------------------------------------------*/
  610. /*    L i f e  S p a n                                                */
  611. /*                                                                    */
  612. /*    Compute time to run program                                     */
  613. /*--------------------------------------------------------------------*/
  614.  
  615. static time_t LifeSpan( time_t duration, time_t stoptime )
  616. {
  617.    time_t exittime = LONG_MAX;
  618.    struct tm  *time_record;
  619.    time_t quit;
  620.  
  621. /*--------------------------------------------------------------------*/
  622. /*             Compute relative quitting time, if desired             */
  623. /*--------------------------------------------------------------------*/
  624.  
  625.    if (duration != -1)
  626.       exittime = hhmm2sec( duration ) + (now / 60L) * 60L;
  627.  
  628. /*--------------------------------------------------------------------*/
  629. /*    Compute absolute quitting time, if desired.  Must terminate     */
  630. /*    before midnight unless relative time was given as well, in      */
  631. /*    which case it must terminate before relative time would         */
  632. /*    expire.                                                         */
  633. /*--------------------------------------------------------------------*/
  634.  
  635.    if (stoptime != -1)
  636.    {
  637.  
  638. /*--------------------------------------------------------------------*/
  639. /*               Compute the absolute termination time                */
  640. /*--------------------------------------------------------------------*/
  641.  
  642.       time_record = localtime(&now);
  643.       time_record->tm_sec = 0;
  644.       time_record->tm_min = (int) (stoptime % 100);
  645.       time_record->tm_hour= (int) (stoptime / 100);
  646.       quit = mktime(time_record);
  647.  
  648.       if ( quit < now )             /* Number should be in future    */
  649.          quit += hhmm2sec( 2400 );
  650.  
  651. /*--------------------------------------------------------------------*/
  652. /*              Compute default relative time, if needed              */
  653. /*--------------------------------------------------------------------*/
  654.  
  655.       if ( duration == -1 )
  656.       {
  657.          time_record->tm_min = 0;
  658.          time_record->tm_hour= 24;
  659.          exittime = mktime(time_record);
  660.       }
  661.  
  662. /*--------------------------------------------------------------------*/
  663. /*                  Determine if we should use time                   */
  664. /*--------------------------------------------------------------------*/
  665.  
  666.       if ( exittime < quit )
  667.       {
  668.  
  669.          printf("*** Exiting ***\tProgram was to execute until %s",
  670.                      ctime(&quit));
  671.  
  672.          printf("\t\twhich would exceed retirement at %s",
  673.                      ctime(&exittime));
  674.          exit(10);
  675.  
  676.       } /* if ( exittime < now ) */
  677.       else
  678.          exittime = quit;
  679.  
  680.    } /* else if (stoptime != -1) */
  681.  
  682.    if (exittime != LONG_MAX)
  683.       printf("Will terminate upon completion of first event after %s",
  684.               ctime(&exittime));
  685.  
  686.    return exittime;
  687.  
  688. } /* LifeSpan */
  689.  
  690. /*--------------------------------------------------------------------*/
  691. /*    a c t i v e                                                     */
  692. /*                                                                    */
  693. /*    Perform an active (outgoing) poll of other hosts                */
  694. /*--------------------------------------------------------------------*/
  695.  
  696.  static active(char *Rmtname, int debuglevel, const char *logname)
  697.  {
  698.    int result;
  699.  
  700.    if (Rmtname == NULL)             /* Default?                         */
  701.    {                                /* Yes --> do -s all and -s any     */
  702.       if (active("all",debuglevel, logname ) < 100)
  703.          return active("any",debuglevel, logname);
  704.       else
  705.          return 100;
  706.    }
  707.    else {
  708.       char buf[128];
  709.       sprintf(buf,"uucico -r 1 -s %s -x %d",Rmtname,debuglevel);
  710.  
  711.       if ( logname != NULL )
  712.          strcat( strcat( buf, " -l ") , logname );
  713.  
  714.       result = runCommand(buf, TRUE);
  715.       if ( result == 0 )
  716.          uuxqt( debuglevel, equal(Rmtname, "all") ? TRUE : FALSE );
  717.  
  718.       printmsg(2,"active: Return code = %d", result );
  719.  
  720.       return result;
  721.    }
  722.  } /* active */
  723.  
  724. /*--------------------------------------------------------------------*/
  725. /*    b u s y w o r k                                                 */
  726. /*                                                                    */
  727. /*    Waits for next time to poll without answering the telephone.    */
  728. /*    Maybe we should at least beep on the hour?  :-)                 */
  729. /*--------------------------------------------------------------------*/
  730.  
  731. static void busywork( time_t next)
  732. {
  733.    time_t naptime;
  734.    time_t hours, minutes, seconds;
  735.  
  736.    naptime = next - now;
  737.  
  738.    hours   = (naptime / 3600) % 24;    /* Get pretty time to display... */
  739.    minutes = (naptime / 60) % 60;
  740.    seconds = naptime % 60;
  741.  
  742.    printf("Going to sleep for %02ld:%02ld:%02ld, next poll is %s",
  743.              hours, minutes, seconds, ctime(&next) );
  744.    ssleep( naptime );
  745.  
  746.    time( & now );
  747. }
  748.  
  749.  
  750. /*--------------------------------------------------------------------*/
  751. /*    r u n C o m m a n d                                             */
  752. /*                                                                    */
  753. /*    Executes a command via a spawn() system call.  This avoids      */
  754. /*    the storage overhead of COMMAND.COM and returns the actual      */
  755. /*    return code from the command executed.                          */
  756. /*                                                                    */
  757. /*    Note that this does not allow quoted command arguments, which   */
  758. /*    not a problem for the intended argv[0]s of UUCICO.              */
  759. /*--------------------------------------------------------------------*/
  760.  
  761.  static int runCommand( char *command, const boolean sync)
  762.  {
  763.    int result;
  764.  
  765. #ifdef DEBUG
  766.    FILE *stream = NULL;
  767. #endif
  768.  
  769.    printf("Executing command: %s\n",command);
  770. #ifdef DEBUG                  /* ahd */
  771.    stream = fopen("UUPOLL.LOG","a");
  772.    if (stream == NULL)
  773.    {
  774.       printerr("UUPOLL.LOG");
  775.       panic();
  776.    } /* if */
  777.    fprintf(stream, "%s: %s\n",arpadate(), command);
  778.    fclose(stream);
  779. #endif /* DEBUG */
  780.  
  781.    result = executeCommand( command, NULL, NULL, sync, FALSE );
  782.  
  783.    if ( result < 0 )
  784.    {
  785.       printf("\a\nCommand \"%s\" failed completely.\n\a", command);
  786.       panic();
  787.    }
  788.  
  789.    time( & now );
  790.  
  791.    return result;
  792. } /* runCommand */
  793.  
  794. /*--------------------------------------------------------------------*/
  795. /*    n e x t p o l l                                                 */
  796. /*                                                                    */
  797. /*    Returns next time to poll in seconds                            */
  798. /*                                                                    */
  799. /*    modified 14 October 1990 By Ed Keith.                           */
  800. /*    modified 4 November 1990 by Drew Derbyshire.                    */
  801. /*--------------------------------------------------------------------*/
  802.  
  803. static time_t nextpoll( hhmm first, hhmm interval )
  804. {
  805.    time_t sfirst;
  806.    time_t sinterval = hhmm2sec( interval );
  807.    time_t today;
  808.    time_t tomorrow;
  809.    struct tm  *time_record;   /* Ed K. 10/14/1990 */
  810.  
  811.    time_record = localtime(&now); /* Ed K. 10/14/1990 */
  812.    time_record->tm_sec = 0;   /* Ed K. 10/14/1990 */
  813.    time_record->tm_min = 0;   /* Ed K. 10/14/1990 */
  814.    time_record->tm_hour= 0;   /* Ed K. 10/14/1990 */
  815.    today = mktime(time_record);
  816.  
  817. /*--------------------------------------------------------------------*/
  818. /*    We could just add hhmm2sec(2400) (24 hours) except this         */
  819. /*    doesn't work during days when we do a daylight savings          */
  820. /*    shift.  So we let the run time library compute midnight.        */
  821. /*--------------------------------------------------------------------*/
  822.  
  823.    time_record->tm_hour = 23;   /* Advance to midnight     */
  824.    time_record->tm_min  = 59;
  825.    tomorrow = mktime(time_record) + 60;   /* Add a minute to 23:59   */
  826.  
  827.    sfirst = today + hhmm2sec(first);
  828.  
  829.    while (sfirst <= now)         // Insure we never return "now" for next
  830.       sfirst += sinterval;
  831.  
  832. /*--------------------------------------------------------------------*/
  833. /*    Since we restart the polling of each day anew, reset the        */
  834. /*    next poll time based if it is after midnight.  Note the         */
  835. /*    funny double compare, which handles the stricter of the two     */
  836. /*    tests for "tomorrow".                                           */
  837. /*--------------------------------------------------------------------*/
  838.  
  839.    if ((sfirst > tomorrow) || (sfirst > (today + hhmm2sec(2400))))
  840.       sfirst = tomorrow + hhmm2sec(first);
  841.  
  842.    return sfirst;
  843.  
  844. } /* nextpoll */
  845.  
  846.  
  847. /*--------------------------------------------------------------------*/
  848. /*    f i r s t p o l l                                               */
  849. /*                                                                    */
  850. /*    Determine first time to poll if not specified                   */
  851. /*--------------------------------------------------------------------*/
  852.  
  853. static hhmm firstpoll(hhmm interval)
  854. {
  855.    struct tm  *time_record;
  856.    time_t sfirst;
  857.    hhmm first;
  858.  
  859.    time_record = localtime(&now);
  860.    sfirst = ((time_t) time_record->tm_hour * 3600L +
  861.              (time_t) time_record->tm_min * 60L);
  862.    sfirst  = sfirst % hhmm2sec(interval);
  863.    first = (hhmm) ((sfirst / 3600L) * 100L + (sfirst % 3600L) / 60L);
  864.  
  865.    printf("First polling time computed to be %-2.2d:%-2.2d\n",
  866.          first / 100, first % 100);
  867.  
  868.    return first;
  869.  
  870. } /* firstpoll */
  871.  
  872. /*--------------------------------------------------------------------*/
  873. /*    n o t a n u m b e r                                             */
  874. /*                                                                    */
  875. /*    Examines string, returns true if non-numeric                    */
  876. /*--------------------------------------------------------------------*/
  877.  
  878.  static boolean notanumber( char *start)
  879.  {
  880.    char *number = start;
  881.    while (*number != '\0')
  882.    {
  883.       if (!isdigit(*number))
  884.       {
  885.          printf("Parameter must be numeric, was %s\n",start);
  886.          return TRUE;
  887.       }
  888.       number++;
  889.    }
  890.    return FALSE;
  891.  } /* notanumber */
  892.  
  893.  
  894. /*--------------------------------------------------------------------*/
  895. /*    p a s s i v e                                                   */
  896. /*                                                                    */
  897. /*    Invoke UUCICO in passive mode until next active poll (if any).  */
  898. /*--------------------------------------------------------------------*/
  899.  
  900.  static int passive( time_t next,
  901.                      int debuglevel,
  902.                      const char *logname,
  903.                      const char *modem )
  904.  {
  905.    char buf[128];             /* Buffer for runCommand() commands       */
  906.    time_t seconds = (next - now + 59);
  907.    time_t minutes;
  908.    int result;
  909.  
  910.    if ( seconds > SHRT_MAX)
  911.       seconds = (SHRT_MAX / 3600) * 3600;
  912.  
  913.    minutes = seconds / 60;
  914.  
  915.    sprintf(buf,"uucico -r 0 -x %d -d %02ld%02ld",
  916.                debuglevel,
  917.                minutes / 60, minutes % 60);
  918.  
  919.    if ( logname != NULL )
  920.       strcat( strcat( buf, " -l ") , logname );
  921.  
  922.    if ( modem != NULL )
  923.       strcat( strcat( buf, " -m ") , modem );
  924.  
  925.    result = runCommand(buf, TRUE);
  926.  
  927.    printmsg(2,"passive: Return code = %d", result );
  928.    return result;
  929.  
  930.  } /* passive */
  931.  
  932. /*--------------------------------------------------------------------*/
  933. /*    u u x q t                                                       */
  934. /*                                                                    */
  935. /*    Execute the UUXQT program to run files received by UUCICO       */
  936. /*--------------------------------------------------------------------*/
  937.  
  938.  static void uuxqt( const int debuglevel, boolean sync)
  939.  {
  940.    int result;
  941.    char buf[128];             /* Buffer for runCommand() commands       */
  942.  
  943.    sprintf(buf,"uuxqt -x %d", debuglevel);
  944.  
  945. #ifdef _Windows
  946.    sync = sync && bflag[F_WINDOWS];
  947. #else
  948.    sync = TRUE;               // Silly hack
  949. #endif
  950.  
  951.    result = runCommand( buf, sync );
  952.  
  953.    if ( result != 0 )
  954.    {
  955.       printf("UUXQT failed with a return code of %d\n",result);
  956.       panic();
  957.    } /* if ( result != 0 ) */
  958.  
  959.    if ( ! sync )
  960.       ssleep(10);
  961.  
  962.  } /* uuxqt */
  963.  
  964. /*--------------------------------------------------------------------*/
  965. /*    C a t c h e r                                                   */
  966. /*                                                                    */
  967. /*    Catch Ctrl-Break                                                */
  968. /*--------------------------------------------------------------------*/
  969.  
  970. #ifdef __TURBOC__
  971. #pragma argsused
  972. #endif
  973.  
  974.  void
  975. #ifdef __TURBOC__
  976. __cdecl
  977. #endif
  978.  Catcher( int sig )
  979.  {
  980.  
  981.     safeout("uupoll: Program aborted by user\r\n");
  982.  
  983.     _exit(100);
  984.  } /* Catcher */
  985.  
  986. /*--------------------------------------------------------------------*/
  987. /*    u s a g e                                                       */
  988. /*                                                                    */
  989. /*    Report correct usage of the program and then exit.              */
  990. /*--------------------------------------------------------------------*/
  991.  
  992.  static void usage( char *name )
  993.  {
  994.  
  995.    printf("Usage:\t%s"
  996.           "\t[-a hhmm] [-d hhmm | -e hhmm] [-f hhmm] [-i hhmm]\n"
  997.           "\t\t[-l logname] [-c hhmm] [-C command]\n"
  998.           "\t\t[-r 0 | 1] [-s system] [-x n]\n",name);
  999.    exit(4);
  1000.  
  1001.  } /* usage */
  1002.  
  1003. #if !defined(NOCBREAK) && !defined(__TURBOC__)
  1004.  
  1005. /*--------------------------------------------------------------------*/
  1006. /*    s e t c b r k                                                   */
  1007. /*                                                                    */
  1008. /*    Enable Cntrl-Break                                              */
  1009. /*                                                                    */
  1010. /*    Written by Dave Watt                                            */
  1011. /*--------------------------------------------------------------------*/
  1012.  
  1013. static int setcbrk(char state)
  1014. {
  1015.    union REGS inregs, outregs;
  1016.  
  1017.    inregs.x.ax = 0x3302;
  1018.    inregs.h.dl = state;
  1019.    intdos(&inregs, &outregs);
  1020.  
  1021.    return outregs.h.dl;
  1022.  
  1023. } /* setcbrk */
  1024.  
  1025. #endif
  1026.